//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <commuTypes.h>
#include <osdepend.h>
#include <commuErr.h>
#include <channelEvent.h>

static WaitReply *s_waitReplyList;
static C_LOCK s_LockOfwaitEList;

EXTERN_C C_INT CreateChannelEventStorage()
{
    s_waitReplyList = (WaitReply *)MALLOC(sizeof(WaitReply));
    if (NULL == s_waitReplyList) {
        COMMU_PRINTF("ERR: OUT OF MEMORY! file%s. line:%d.\n",
                    __FILE__, __LINE__);
        return C_OUT_OF_MEMORY;
    }
    memset((C_VOID *)s_waitReplyList, 0, sizeof(WaitReply));

    s_LockOfwaitEList = InitLock();
    if (NULL == s_LockOfwaitEList) {
        COMMU_PRINTF("ERR: Init Lock fail! file%s. line:%d.\n",
                    __FILE__, __LINE__);
        return C_OUT_OF_MEMORY;
    }

    return 0;
}

EXTERN_C C_VOID DelChannelEventStorage()
{
    WaitReply *pDelWaitNode = NULL;

    while (NULL != s_waitReplyList) {
        pDelWaitNode = s_waitReplyList;
        s_waitReplyList = s_waitReplyList->next;
        if(NULL != pDelWaitNode->event)DeleEvent(pDelWaitNode->event);
        FREE(pDelWaitNode);
    }

    DeleLock(s_LockOfwaitEList);
}

EXTERN_C C_INT CreateWaitReply(C_UINT channel_number, WaitReply** ppNode)
{
    C_EVENT event = NULL;
    WaitReply *pNode;
    pNode = (WaitReply *)MALLOC(sizeof(WaitReply));
    if (NULL == pNode) {
        COMMU_PRINTF("ERR: OUT OF MEMORY! file%s. line:%d.\n",
                    __FILE__, __LINE__);
        return C_OUT_OF_MEMORY;
    }
    memset((C_VOID *)pNode, 0, sizeof(WaitReply));

    event = EventCreate(FALSE);
    if (NULL == event) {
        COMMU_PRINTF("ERR: Create Event failed! file%s. line:%d. channel_number:%d.\n",
                __FILE__, __LINE__, channel_number);
        return C_FAIL;
    }

    pNode->channel_number = channel_number;
    pNode->event = event;
    Lock(s_LockOfwaitEList);
    pNode->next = s_waitReplyList->next;
    pNode->prev = s_waitReplyList;
    if (NULL != s_waitReplyList->next) {
        s_waitReplyList->next->prev = pNode;
    }
    s_waitReplyList->next = pNode;
    UnLock(s_LockOfwaitEList);
    *ppNode = pNode;
    return 0;
}

EXTERN_C void ReleaseWaitReply(WaitReply* pNode)
{
    assert(NULL != pNode);
    Lock(s_LockOfwaitEList);
    pNode->prev->next = pNode->next;
    if (NULL != pNode->next) {
        pNode->next->prev = pNode->prev;
    }
    DeleEvent(pNode->event);
    FREE(pNode);
    UnLock(s_LockOfwaitEList);
}

EXTERN_C C_INT NotifyChannelEvent(C_UINT channel_number, C_BOOL bReply)
{
    WaitReply *pWaitReply = NULL;
    C_EVENT event = NULL;

    Lock(s_LockOfwaitEList);
    pWaitReply = s_waitReplyList->next;
    while (NULL != pWaitReply) {
        if (pWaitReply->channel_number == channel_number) {
            event = pWaitReply->event;
            pWaitReply->bTransSucceed = bReply;
            break;
        }
        pWaitReply = pWaitReply->next;
    }
    UnLock(s_LockOfwaitEList);
    if (NULL == event) {
        COMMU_PRINTF("Can not find wait reply! file%s. line:%d. channel_number:%d.\n",
                __FILE__, __LINE__, channel_number);
        return C_INVALID_ARGUMENT;
    }

    if (!EventSet(event)) {
        COMMU_PRINTF("ERR: Set Event failed! file%s. line:%d. channel_number:%d.\n",
                __FILE__, __LINE__, channel_number);
    }

    return 0;
}
